package project3;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

import project3.association.Apriori;
import project3.association.AssociationRule;
import project3.association.ItemSet;
import project3.association.RuleToString;
import project3.datasets.DefaultDataSet;
import project3.datasets.parsers.CsvParser;
import project3.util.Trace;

public class Main {

	public static void main(String[] args) throws Exception {
		
		String fileName = "INTEGRATED-DATASET.csv";
		double minConfidence = 0.3;
		double minSupport = 0.2;
		
		if(args.length == 3) {
			fileName = args[0];
			minSupport = Double.parseDouble(args[1]);
			minConfidence = Double.parseDouble(args[2]);
		}
		
		Trace.info("Processing file " + fileName + " Conf: " + minConfidence + " Support: " + minSupport);
		
		// parser the file
		CsvParser parser = new CsvParser("someDataSet", fileName);
		
		// create dataset
		DefaultDataSet dataSet = new DefaultDataSet(parser);
		
		// run Apriori
		Apriori apriori = new Apriori(minSupport, minConfidence, dataSet);
		Map<Integer, List<ItemSet>> itemSets = apriori.extractLargeItemsets();
		
		RuleToString rts = new RuleToString(dataSet);
		
		AssociationRule[] rules = null;
		
		// output results
		BufferedWriter out = new BufferedWriter(new FileWriter("output.txt"));

		if(itemSets != null) {
			printLargeItemsets(out, rts, itemSets);
		    rules = apriori.extractAssociationRules(itemSets);
		}
		
		if (rules != null)
			printAssociationRules(out, rts, rules);
		
		out.close();

	}
	
	// Print Association Rules
	public static void printAssociationRules(BufferedWriter out, RuleToString rts, AssociationRule[] rules) {
	
		TreeMap<Double, AssociationRule> sortedMap = new TreeMap<Double, AssociationRule>();
		
		try {
			//Trace.info("\nAssociation Rules: ");
			out.write("\nAssociation Rules: \n");
			
			for (int i = 0 ; i < rules.length; ++i){
				sortedMap.put(rules[i].getConfidence(), rules[i]);
			}
			
			Collection<AssociationRule> c = sortedMap.descendingMap().values();
			Iterator<AssociationRule> itr = c.iterator();
		
			while(itr.hasNext()) {
				AssociationRule aRule = (AssociationRule)itr.next();
			
				//Trace.info(rts.toString(aRule));
				out.write(rts.toString(aRule)+"\n");
			}
			
		} catch (IOException e) {
			
		}
	}
	
	// Print Large Itemsets
    public static void printLargeItemsets(BufferedWriter out, RuleToString rts, Map<Integer, List<ItemSet>> itemSets){
    	
		TreeMap<Integer, ItemSet> sortedMap = new TreeMap<Integer, ItemSet>();
		
		try {
			//Trace.info("\nLarge Itemsets: ");
			out.write("\nLarge Itemsets: \n");
			
			for (Map.Entry<Integer, List<ItemSet>> entry : itemSets.entrySet())
			{
				Iterator<ItemSet> itr = entry.getValue().iterator();
				while(itr.hasNext()) {
					ItemSet itemSet = itr.next();
					sortedMap.put(itemSet.getSupport(), itemSet);
				}
			}
		
			Collection<ItemSet> c = sortedMap.descendingMap().values();
			Iterator<ItemSet> itr = c.iterator();
		
			while(itr.hasNext()) {
				ItemSet itemSet = (ItemSet)itr.next();
			
				StringBuilder buff = new StringBuilder();
				rts.itemSetToString(itemSet, buff, true);
			
				//Trace.info(buff.toString());
				out.write(buff.toString() + "\n");
			}
		} catch (IOException e) {
			
		}
    }
		
}
